package cn.lqz.bucttrain.service.impl;

import cn.lqz.bucttrain.context.BaseContext;
import cn.lqz.bucttrain.enums.ResponseCodeEnum;
import cn.lqz.bucttrain.enums.UserRoleTypeEnum;
import cn.lqz.bucttrain.enums.UserStatusEnum;
import cn.lqz.bucttrain.exceptions.BaseException;
import cn.lqz.bucttrain.mapper.UserMapper;
import cn.lqz.bucttrain.pojo.dto.TokenUserInfoDTO;
import cn.lqz.bucttrain.pojo.dto.UserLoginDTO;
import cn.lqz.bucttrain.pojo.dto.UserPasswordChangeDTO;
import cn.lqz.bucttrain.pojo.entity.User;
import cn.lqz.bucttrain.redis.RedisService;
import cn.lqz.bucttrain.service.AccountService;
import cn.lqz.bucttrain.utils.StringUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

/**
 * 用户登录
 */
@Service
@Slf4j
public class AccountServiceImpl implements AccountService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private RedisService redisService;
    /**
     * 登录
     * @param userLoginDTO
     * @return
     */
    @Override
    public TokenUserInfoDTO login(UserLoginDTO userLoginDTO) {
        log.info("登录：{}",userLoginDTO);

        String phoneNumber = userLoginDTO.getPhoneNumber();
        String password = userLoginDTO.getPassword();
        User existUser = userMapper.findByPhoneNumberAndPassword(phoneNumber, password);
        // 账号密码错误
        if (null==existUser){
            throw new BaseException(ResponseCodeEnum.CODE_400.getCode(),"账号或密码错误");
        }
        // 用户不是管理员
        if (!UserRoleTypeEnum.ADMIN.getType().equals(existUser.getRoleType())){
            throw new BaseException(ResponseCodeEnum.CODE_400.getCode(),"无权登录");
        }
        // 用户被禁用
        if (UserStatusEnum.DISABLE.getStatus().equals(existUser.getStatus())){
            throw new BaseException(ResponseCodeEnum.CODE_400.getCode(),"用户已被禁用");
        }

        String token = StringUtils.getUserToken(existUser.getUserId());

        // 用户已登录
        TokenUserInfoDTO existTokenUserInfoDTO = redisService.getTokenUserInfoDTO(token);
        if (null!=existTokenUserInfoDTO){
            throw new BaseException(ResponseCodeEnum.CODE_400.getCode(),"用户已登录");
        }

        // 生成TokenUserInfoDTO
        TokenUserInfoDTO tokenUserInfoDTO = new TokenUserInfoDTO();
        BeanUtils.copyProperties(existUser,tokenUserInfoDTO);
        tokenUserInfoDTO.setToken(token);

        // redis存储用户信息
        redisService.saveTokenUserInfoDTO(token,tokenUserInfoDTO);

        return tokenUserInfoDTO;
    }
    /**
     * 退出登录
     * @param userId
     * @return
     */
    public void logout(Long userId){
        log.info("退出登录：userId={}",userId);
        User existUser = userMapper.findByUserId(userId);
        // 用户是否存在
        if (null==existUser){
            throw new BaseException(ResponseCodeEnum.CODE_600);
        }
        // 当前操作用户是否拥有权限
        TokenUserInfoDTO tokenUserInfo = BaseContext.getTokenUserInfo();
        // 执行当前操作的用户id == 与要退出登录的用户id
        if (!tokenUserInfo.getUserId().equals(userId)){
            throw new BaseException(ResponseCodeEnum.CODE_600);
        }
        // 清除redis缓存
        redisService.removeTokenUserInfoDTO(tokenUserInfo.getToken());
    }
    /**
     * 修改密码
     * @param userPasswordChangeDTO
     */
    public void changePassword(UserPasswordChangeDTO userPasswordChangeDTO){
        Long userId = userPasswordChangeDTO.getUserId();
        String oldPassword = userPasswordChangeDTO.getOldPassword();
        String newPassword = userPasswordChangeDTO.getNewPassword();
        log.info("修改密码：userId={}",userId);
        // 当前操作用户是否拥有权限
        TokenUserInfoDTO tokenUserInfo = BaseContext.getTokenUserInfo();
        if (!tokenUserInfo.getUserId().equals(userId)){
            throw new BaseException(ResponseCodeEnum.CODE_600);
        }
        User existUser = userMapper.findByUserId(userId);
        // 用户是否存在或旧密码是否匹配
        if (null==existUser || !existUser.getPassword().equals(oldPassword)){
            throw new BaseException(ResponseCodeEnum.CODE_400.getCode(),"旧输入密码错误");
        }
        // 修改密码
        User userFoUpdate = new User();
        userFoUpdate.setUserId(userId);
        userFoUpdate.setPassword(newPassword);
        userMapper.update(userFoUpdate);
    }

    /**
     * 获取短信验证码
     * @param phoneNumber
     */
    @Override
    public void getCheckCode(String phoneNumber) {
        log.info("获取短信验证码：phoneNumber={}",phoneNumber);
        redisService.saveCheckCode(phoneNumber,StringUtils.generateCheckCode());
    }

    /**
     * 校验短信验证码
     * @param phoneNumber
     * @param checkCode
     */
    @Override
    public void submitCheckCode(String phoneNumber, String checkCode) {
        log.info("校验短信验证码：phoneNumber={},checkCode={}",phoneNumber,checkCode);
        String correctCheckCode = redisService.getCheckCode(phoneNumber);
        if (correctCheckCode==null || !correctCheckCode.equals(checkCode)){
            throw new BaseException(ResponseCodeEnum.CODE_400.getCode(),"验证码错误");
        }
        // 清除redis验证码缓存
        redisService.removeCheckCode(phoneNumber);
    }

    /**
     * 忘记密码并修改密码
     * @param phoneNumber
     * @param newPassword
     */
    @Override
    public void forgetAndChangePassword(String phoneNumber, String newPassword) {
        log.info("忘记密码并修改密码：phoneNumber={}",phoneNumber);
        User existUser = userMapper.findByPhoneNumber(phoneNumber);
        // 用户是否存在
        if (null==existUser){
            throw new BaseException(ResponseCodeEnum.CODE_400.getCode(),"用户不存在");
        }
        // 修改密码
        User userFoUpdate = new User();
        userFoUpdate.setUserId(existUser.getUserId());
        userFoUpdate.setPassword(newPassword);
        userMapper.update(userFoUpdate);
    }
}
